/*
 * FilePath     : \src\utils\http.ts
 * Author       : 苏军志
 * Date         : 2023-06-04 17:25
 * LastEditors  : 苏军志
 * LastEditTime : 2025-01-17 17:25
 * Description  : 访问后端API工具类
 * CodeIterationRecord:
 */

import common from "@/utils/common";
import { hideLoading, showLoading } from "@/utils/loading";
import logger from "@/utils/logger";
import { showMessage } from "@/utils/message";
import axios from "axios";

const win = window as any;
// 阻止Promise抛出reject但是没有写catch
win.onunhandledrejection = (event: any) => {
  // 不兼容ie
  event.preventDefault();
};
// 在window上添加apiRequestList属性
win.apiRequestList = [];
const http = axios.create({
  // timeout: 5000,
  withCredentials: false
});

// 获取key
const getUrlKey = (config?: any, isRemove?: boolean | undefined) => {
  let url = config?.baseURL + config?.url;
  let urlKey = url + "||" + config?.method;
  if (config?.method === "get") {
    if (!isRemove) {
      urlKey = encodeURIComponent(urlKey + "||" + JSON.stringify(config?.params));
    }
  } else if (!isRemove) {
    urlKey = encodeURIComponent(urlKey + "||" + JSON.stringify(config?.data));
  }
  return urlKey;
};
// 根据key获取请求对象
const isExistRequest = (urlKey: string) => {
  if (urlKey) {
    let request = win.apiRequestList.find((request: any) => {
      return request.key === urlKey;
    });
    if (request) {
      return true;
    }
  }
  return false;
};

const removeRequest = function (config: any) {
  // 请求结束把本次请求从请求集合中移除
  let urlKey = getUrlKey(config, true);
  if (urlKey) {
    win.apiRequestList = win.apiRequestList.filter((request: any) => {
      return request.key.indexOf(urlKey) !== -1;
    });
  }
};

/**
 * 请求拦截
 */
http.interceptors.request.use((config: any) => {
  // 头部设置token
  config.headers["Management-Token"] = common.session("session")?.token;
  if (config.contentType) {
    config.headers["Content-Type"] = config.contentType;
  }
  config.headers["Is-Inner-Server"] = common.storage("isInnerServer") ?? false;
  // 设置取消机制
  let tempCancel: any = undefined;
  config.cancelToken = new axios.CancelToken((cancel: any) => {
    tempCancel = cancel;
  });
  // 判断当前请求是否存在
  let urlKey = getUrlKey(config, false);
  if (isExistRequest(urlKey)) {
    // 已存在相同请求则把本次请求取消
    if (tempCancel) {
      // @ts-ignore
      tempCancel("repeat||" + decodeURIComponent(urlKey));
    }
  } else {
    // 不存在 则把本次请求添加到请求集合里
    let request = {
      key: urlKey,
      excludeCancelTypes: config.excludeCancelTypes,
      cancel: (msg: string) => {
        tempCancel(msg);
        // config?.loadingText && hideLoading();
      }
    };
    win.apiRequestList.push(request);
    // 写日志
    logger.setLogger({
      title: "请求接口",
      api: config.baseURL + config.url,
      content: JSON.stringify(config.data)
    });
    // 显示loading
    config?.loadingText && showLoading(config.loadingText);
  }
  return config;
});

/**
 * 响应拦截
 */
http.interceptors.response.use(
  (response: any) => {
    // 关闭loading
    response.config?.loadingText && hideLoading();
    // 增加延迟，相同请求不得在短时间内重复发送
    setTimeout(() => {
      removeRequest(response.config);
    }, 1000);
    const res = JSON.parse(response.request.response);
    logger.setLogger({
      title: "接口响应",
      api: response.request.responseURL,
      content: `响应代码：${res.code}，响应信息：${res.message}`
    });
    return response;
  },
  (error: any) => {
    // 关闭loading
    error.config?.loadingText && hideLoading();
    // 打印取消请求信息
    if (axios.isCancel(error) && error && error.message) {
      // 目前手动取消请求信息格式：type||url||method||params,type标识取消原因类型
      let info = error.message.split("||");
      let title: string | undefined = undefined;
      let content: string | undefined = undefined;
      if (info && info.length === 4) {
        if (info[0] === "repeat") {
          title = "拦截到重复请求，取消本次请求";
          console.groupCollapsed("拦截到重复请求，取消本次请求");
        } else if (info[0] == "refresh") {
          title = "页面刷新，取消未完成的请求";
          console.groupCollapsed("页面刷新，取消未完成的请求");
        } else {
          title = "页面切换，取消未完成的请求";
          console.groupCollapsed("页面切换，取消未完成的请求");
        }
        content = `url:${info[1]},method:${info[2]},params:${info[3]}`;
        console.log("url:", info[1]);
        console.log("method:", info[2]);
        console.log("params:", JSON.parse(info[3]));
        console.log("history:", win.apiRequestList);
        console.groupEnd();
      } else {
        title = error ? error.message : "请求取消";
        console.log("%c" + error ? error.message : "请求取消", "color:#ff0000;");
      }
      logger.setLogger({
        title,
        content
      });
      return error;
    }
    if (error.response && error.response.status == 401) {
      let session = common.session("session");
      session.token = "";
      common.session("session", session);
      showMessage("warning", "登陆超时！请重新登录!");
    } else {
      showMessage("warning", "服务器异常！");
    }
    // 增加延迟，相同请求不得在短时间内重复发送
    setTimeout(() => {
      removeRequest(error.config);
    }, 1000);
    return error;
  }
);

/**
 * @description: 拦截判断API返回是否成功
 * @param response
 * @return
 */
const isSuccess = (response: any) => {
  return new Promise((resolve, reject) => {
    // 失败
    if (!response || response.code === 0) {
      response?.message && showMessage("error", response?.message);
      reject(response?.message);
    } else {
      // 成功
      resolve(response.data);
    }
  });
};

export default {
  /**
   * @description: 设置ApiUrl
   * @param url ApiUrl
   * @return
   */
  setApiUrl(url: string) {
    http.defaults.baseURL = url;
  },
  /**
   * @description: get请求
   * @param url 请求api
   * @param params 参数
   * @param config 配置项
   * @return
   */
  get(url: string, params?: any, config?: Record<string, any>) {
    if (!http.defaults.baseURL) {
      http.defaults.baseURL = common.session("serverUrl");
    }
    return new Promise((resolve, reject) => {
      http
        .get(url, { params, ...config })
        .then((response: any) => {
          if (response) {
            resolve(isSuccess(response.data));
          }
        })
        .catch((error: any) => {
          error && showMessage("error", error);
        });
    });
  },
  /**
   * @description: get请求
   * @param url 请求api
   * @param params 参数
   * @param config 配置项
   * @return
   */
  post(url: string, params?: any, config?: Record<string, any>) {
    if (!http.defaults.baseURL) {
      http.defaults.baseURL = common.session("serverUrl");
    }
    return new Promise((resolve, reject) => {
      http
        .post(url, params, config as any)
        .then((response: any) => {
          if (response) {
            resolve(isSuccess(response.data));
          }
        })
        .catch((error: any) => {
          error && showMessage("error", error);
        });
    });
  },
  /**
   * @description: 刷新前取消未完成的请求
   */
  cancelPageRequest() {
    // 刷新前取消未完成的请求
    if (win.apiRequestList?.length) {
      win.apiRequestList.forEach((request: any) => {
        if (!request.key.includes("SaveLog")) {
          request.cancel("refresh||" + decodeURIComponent(request.key));
        }
      });
      win.apiRequestList = [];
    }
  }
};
